/*
 * kernel/mktime.c
 *
 * last modified by ChenJie at 2007.07.22
 *
 */

#include <cos/time.h>
#include <cos/kernel.h>
#include <cos/protect.h>

#define MINUTE	(60)
#define HOUR	(60 * MINUTE)
#define DAY	(24 * HOUR)
#define YEAR	(365 * DAY)

#define CMOS_READ(addr)		({ \
		outb(0x80|addr, 0x70); \
		inb(0x71); \
		})

#define BCD_TO_BIN(val)	((val)=((val)&15)+((val)>>4)*10)

static int month[12] = {
	0,
	DAY*(31),
	DAY*(31+29),
	DAY*(31+29+31),
	DAY*(31+29+31+30),
	DAY*(31+29+31+30+31),
	DAY*(31+29+31+30+31+30),
	DAY*(31+29+31+30+31+30+31),
	DAY*(31+29+31+30+31+30+31+31),
	DAY*(31+29+31+30+31+30+31+31+30),
	DAY*(31+29+31+30+31+30+31+31+30+31),
	DAY*(31+29+31+30+31+30+31+31+30+31+30)
};

//内核开始时间:
unsigned long startup_time = 0;

struct tm * gettime(struct tm *t)
{
	int centry = 0;
	if(t==0) return 0;
	do {
		t->tm_sec = CMOS_READ(0);
		t->tm_min = CMOS_READ(2);
		t->tm_hour = CMOS_READ(4);
		t->tm_wday = CMOS_READ(6);
		t->tm_mday = CMOS_READ(7);
		t->tm_mon = CMOS_READ(8);
		t->tm_year = CMOS_READ(9);
		centry = CMOS_READ(0x32);
	}while(t->tm_sec != CMOS_READ(0));
	BCD_TO_BIN(t->tm_sec);
	BCD_TO_BIN(t->tm_min);
	BCD_TO_BIN(t->tm_hour);
	BCD_TO_BIN(t->tm_mday);
	BCD_TO_BIN(t->tm_mon);
	BCD_TO_BIN(t->tm_year);
	BCD_TO_BIN(centry);
	t->tm_year += centry * 100;
	t->tm_mon--; //tm中的tm_mon 的范围是0~11
	return t;
}


long kernel_mktime(struct tm * tm)
{
	long res;
	int year;
	year = tm->tm_year - 1970;
	res = YEAR * year + DAY * ((year+1)/4);
	res += month[tm->tm_mon];
	if(tm->tm_mon > 1 && ((year+2)%4))
		res -= DAY;
	res += DAY * (tm->tm_mday-1);
	res += HOUR * tm->tm_hour;
	res += MINUTE * tm->tm_min;
	res += tm->tm_sec;
	return res;
}

void time_init(void)
{
	struct tm time;
	startup_time = kernel_mktime(gettime(&time));
}

void showtime(void)
{
	static int interval = 5;
	if(--interval) return;
	interval = 5;
	struct tm t;
	gettime(&t);
	xycprintk(0, 24, TEXT_FR_I|TEXT_FR_G,"%4d:%02d:%02d %02d:%02d:%02d", 
			t.tm_year, t.tm_mon+1, t.tm_mday,
			t.tm_hour, t.tm_min, t.tm_sec);
	
}



